package com.xxl.job.executor.plugin;

import com.xxl.job.core.context.XxlJobHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

public class JPubUtils {
    private static final Logger logger = LoggerFactory.getLogger(JPubUtils.class);

    public static String jwt_Secret="";

    //Token默认12小时
    public static int jwt_expiration=43200;

    public static String jwt_token="";

    public static int login_maxfailtimes=5;
    public static boolean login_allowdefaultpwd=true;
    public static String login_defaultpwd="Ccrm@./123456";

    public static String token_userheader="online_@";
    public static String token_header="token_@@Bearer ";

    public static String STAR_PHN="phone";
    public static String STAR_IDNO="idno";
    public static String STAR_CARD="cardno";

    //==2023-06-09
    //默认一次手动分案最多20w条，
    public static Integer distMaxCount=200000;

    //默认案件导出最大2w条，
    public static Integer exportMaxCount=20000;

    //分案时效，默认2小时
    public static Integer distExpiration=3600;

    public static boolean IsEmpty(String str)
    {
        return (str == null ||str.length()==0) ? true : false;
    }

    public static boolean IsTrimEmpty(String str)
    {
        if(IsEmpty(str)) return true;
        if(IsEmpty(str.trim())) return true;
        return false;
    }

    public static boolean IsEmpty(Integer i){
        if(i==null) return true;
        return  false;
    }

    public static boolean IsEmpty(Date d){
        if(d==null) return true;
        return  false;
    }

    public static boolean IsEmpty(List ll){
        if(ll==null) return true;
        if(ll.isEmpty()) return true;
        if(ll.size()==0) return true;
        return  false;
    }

    public static boolean IsNotEmpty(String str){
        return !IsEmpty(str);
    }

    public static boolean IsNotEmpty(Integer i){
        return !IsEmpty(i);
    }

    public static boolean IsNotEmpty(List ll){
        return !IsEmpty(ll);
    }

    public static boolean IsNotEmpty(Date d){
        return !IsEmpty(d);
    }

    public static boolean IsEqual(String str1,String str2)
    {
        if(IsEmpty(str1)){
            if(IsEmpty(str2))
                return true;
            else return false;
        }

        return (str1.equals(str2));
    }

    public static boolean IsNotEqualAndNotNull(String str1,String str2)
    {
        if(IsEmpty(str1)) return false;

        return !IsEqual(str1,str2);
    }

    public static boolean IsEqual(String str1,int ival)
    {
        return IsEqual(str1,String.format("%d",ival));
    }

    public static boolean IsEqual(Date day1,Date day2)
    {
        String s1=DateToString(day1);
        String s2=DateToString(day2);
        return IsEqual(s1,s2);
    }

    public static String Trim(String s){
        if(s==null) return null;
        return s.trim();
    }

    public static int StringToInt(String val)
    {
        int v=0;
        if(IsEmpty(val)) return 0;

        try{
            v=Integer.parseInt(val);
        }
        catch(NumberFormatException e){
            XxlJobHelper.log("无法将字符串转换为整数: " + val);
            v=0;
        };

        return v;
    }

    public static int ObjectToInt(Object val)
    {
        int v=0;
        if(val==null) return 0;

        try{
            v=Integer.parseInt(val.toString());
        }
        catch(NumberFormatException e){
            v=0;
        };

        return v;
    }

    public static String ObjectToString(Object val)
    {
        String v="";
        if(val==null) return "";

        try{
            v=val.toString();
        }
        catch(NumberFormatException e){
            v="";
        };

        return v;
    }

    public static BigDecimal StringToBigDecimal(String val) {
        if (val == null || val.isEmpty()) {
            return BigDecimal.ZERO;
        }

        try {
            return new BigDecimal(val);
        } catch (NumberFormatException e) {
            return BigDecimal.ZERO;
        }
    }

    public static BigDecimal ObjectToBigDecimal(Object val) {
        if (val == null) {
            return BigDecimal.ZERO;
        }

        try {
            if (val instanceof BigDecimal) {
                return (BigDecimal) val;
            } else if (val instanceof Number) {
                return BigDecimal.valueOf(((Number) val).doubleValue());
            } else if (val instanceof String) {
                return new BigDecimal((String) val);
            } else {
                return new BigDecimal(val.toString());
            }
        } catch (NumberFormatException e) {
            return BigDecimal.ZERO;
        }
    }

    public static double ObjectToDouble(Object val)
    {
        if(val==null) return 0.0;
        return StringToDouble(val.toString());
    }

    public static long ObjectToLong(Object val)
    {
        long v=0;
        if(val==null) return 0;

        try{
            v=Long.parseLong(val.toString());
        }
        catch(NumberFormatException e){
            v=0;
        };

        return v;
    }

    public static long StringToLong(String val)
    {
        long v=0;
        if(IsEmpty(val)) return 0;

        try{
            v=Long.parseLong(val);
        }
        catch(NumberFormatException e){
            v=0;
        };

        return v;
    }

    public static double StringToDouble(String val)
    {
        double v=0.0;
        if(IsEmpty(val)) return v;

        try{
            v=Double.parseDouble(val);
        }
        catch(NumberFormatException e){
            v=0.0;
        };

        return v;
    }

    public static boolean StringToBool(String val)
    {
        if(IsEmpty(val)) return false;

        String ret = val.toUpperCase();
        if (ret.equals("TRUE") || ret.equals("1") || ret.equals("Y") || ret.equals("YES") || ret.equals("T"))
            return true;

        return false;
    }

    public static String BoolToString(String val)
    {
        if(IsEmpty(val)) return "0";

        String ret = val.toUpperCase();
        if (ret.equals("TRUE") || ret.equals("1") || ret.equals("Y") || ret.equals("YES") || ret.equals("T"))
            return "1";

        return "0";
    }

    public static Date StringToDate(String val)
    {
        if(IsTrimEmpty(val)) return null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            if(val.length()==16){
                sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            }
            else if(val.length()>16){
                sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }

            return sdf.parse(val);
        }
        catch (Exception e){
            logger.warn("StringToDate.Err:{}",val);
            return null;
        }
    }

    public static String DateToString(Date val)
    {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.format(val);
        }
        catch (Exception e){
            logger.warn("DateToString.Err:{}",val);
            return null;
        }
    }

    public static String DTimeToString(Date val)
    {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(val);
        }
        catch (Exception e){
            logger.warn("DTimeToString.Err:{}",val);
            return null;
        }
    }

    public static String getReqIpAddr(HttpServletRequest request) {
        try {
            String ip = request.getHeader("x-forwarded-for");
            if (ip == null || ip.length() == 0 || "unknow".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            // 多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
            if (ip != null && ip.length() > 15) {
                if (ip.indexOf(",") > 0) {
                    ip = ip.substring(0, ip.indexOf(","));
                }
            }
            return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
        }
        catch(Exception e){
            logger.error("getReqIpAdd",e);
            return "-";
        }
    }

    public static String getReqIpAddr() {
        HttpServletRequest h=((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        return getReqIpAddr(h);
    }

    public static void PrintError(String title,Exception e)
    {
        logger.error("{} Error:{}",title,e);
    }

    public static void PrintInfo(String title,String msg)
    {
        logger.info("{}:{}",title,msg);
    }

    public static void PrintWarn(String title,String msg)
    {
        logger.warn("{}:{}",title,msg);
    }

    public static String getToken(HttpServletRequest request)
    {
        String token = request.getHeader("authorization");
        if(IsNotEmpty(token)){
            return token.substring(7);
        }
        else{
            logger.error("Token:authorization isEmpty:{}",request);
        }

        return "";
    }

    public static String getOnlineTokenKey(String usrid)
    {
        return token_userheader+usrid;
    }

    public static String getTokenKey(String token)
    {
        return token_header+token;
    }

    public static long getTimeSpan(String ts)
    {
        if(IsEmpty(ts)) return 0;
        long ln=StringToLong(ts);
        return ln>0?System.currentTimeMillis()-ln:0;
    }

    public static void Init(Environment environment)
    {
        logger.info("PubUtils.Init...");
        jwt_Secret = environment.getProperty("ccrm.security.jwt.secret");
        int expiration = StringToInt(environment.getProperty("ccrm.security.jwt.expiration"));
        if(expiration>0){
            jwt_expiration=expiration;
        }
        expiration = StringToInt(environment.getProperty("ccrm.security.loginmaxfailtimes"));
        if(expiration>0){
            login_maxfailtimes=expiration;
        }

        String s = environment.getProperty("ccrm.security.allowdefaultpwd");
        if(IsNotEmpty(s)){
            login_allowdefaultpwd=StringToBool(s);
        }
        s=environment.getProperty("ccrm.security.jwt.token");
        if(IsNotEmpty(s)) {
            jwt_token = s;
        }

        s=environment.getProperty("ccrm.security.initpwd");
        if(IsNotEmpty(s)) {
            login_defaultpwd = s.trim();
        }

        s=environment.getProperty("ccrm.distmaxcount");
        if(IsNotEmpty(s)) {
            distMaxCount = StringToInt(s.trim());
        }

        s=environment.getProperty("ccrm.exportmaxcount");
        if(IsNotEmpty(s)) {
            exportMaxCount = StringToInt(s.trim());
        }
        logger.info("Init:jwt.expiration={},maxfailtimes={},allowdefaultpwd={},distmaxcount={},exportmaxcount={}",
                jwt_expiration, login_maxfailtimes, login_allowdefaultpwd,distMaxCount,exportMaxCount);

        if(logger.isDebugEnabled()) {
            logger.debug("Init:jwt.secret={}", jwt_Secret);
        }
        logger.info("Init:token={}",jwt_token);
    }

    public static Date addMonths(Date date, int months)
    {
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH,months);
        return calendar.getTime();
    }

    public static Date addDays(Date date, int days)
    {
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE,days);
        return calendar.getTime();
    }

    public static String getLocalIpAddr() {
        try {
            InetAddress ip4 = Inet4Address.getLocalHost();
            String ip=ip4.getHostAddress();

            logger.info("getLocalIpAddr",ip);

            return ip;
        } catch (UnknownHostException e) {
            PrintError("getLocalIpAddr",e);
        }
        return "";
    }

    public static String getInString(List<String> ls)
    {
        if(ls==null||ls.size()==0)
            return "";
        String s= String.join("','",ls);
        return String.format("%s",s);
    }

    public static String getInString(String vs)
    {
        if(JPubUtils.IsEmpty(vs)) return "";
        String[] ls=vs.split(",");
        if(ls.length<=1) return vs;
        String s= String.join("','",ls);
        return String.format("%s",s);
    }

    public static String getStarString(String name,String val)
    {
        String ret=val;
        if(IsEmpty(val)) return "";
        if(val.length()<6) return val;

        if(name.equals(STAR_PHN)){
            ret=val.substring(0,3)+"****"+val.substring(8);
        }
        else if(name.equals(STAR_IDNO)){
            ret=val.substring(0,6)+"********"+val.substring(15);
        }
        else if(name.equals(STAR_CARD)){
            ret=val.substring(0,4)+"********"+val.substring(13);
        }
        return ret;
    }

    public static String BilldayToStartday(String day)
    {
        if(IsEmpty(day)) return "";

        try{
            Date d=StringToDate(day);
            d=addMonths(d,-1);
            d=addDays(d,1);
            return DateToString(d);
        }
        catch(NumberFormatException e){
            logger.warn("DTimeToString.Err:{}",day);
            return "";
        }
    }

    public static Integer StrDateToInt(String d)
    {
        String s=d.replace("-","");
        return StringToInt(s);
    }

    public static boolean hasValue(List<String> list,String val)
    {
        if(JPubUtils.IsEmpty(list)) return false;
        return list.contains(val);
    }

    public static String RTrimZero(String val)
    {
        if(IsEmpty(val)) return val;
        return val.replaceAll("0+$","");
    }

    public static String LTrimZero(String val)
    {
        if(IsEmpty(val)) return val;
        return val.replaceAll("^0*","");
    }
}
